﻿using ABB.Robotics.Controllers.RapidDomain;
using S7.Net;
using System.Security.Policy;
using System.Text;
using System.Windows;
using System.Windows.Input;
using 小玩意.ViewModel;

namespace 小玩意.Comm
{
    public class Siemens
    {
       public enum Type
       { 
           Bool = 0,
           Int16 =1,
           Int32 = 2,
           String = 3,
           Real = 4,

       }
        
        public bool iSconn;
        public CpuType _cpuType;

        public string _address;
        public short _rack;
        public short _slot;
        public Plc _plc;
        public string value;
        private Dictionary<string, string> addrssList  = new Dictionary<string, string>();
        
        /// <summary>
        /// 初始化PLC
        /// </summary>
        /// <param name="cpuType">CPU类型</param>
        /// <param name="address">地址</param>
        /// <param name="rack">机架号</param>
        /// <param name="slot"></param>
        public Siemens(CpuType cpuType, string address, short rack, short slot)
        {
            if (false)
            {
                this._cpuType = cpuType;
                this._address = address;
                this._rack = rack;
                this._slot = slot;

                this._plc = new Plc(this._cpuType, this._address, this._rack, this._slot);
                if (this._plc != null)
                {
                    Application.Current.Dispatcher.Invoke(new Action(async () =>
                    {
                        this._plc.OpenAsync();
                        if (this._plc.IsConnected)
                        {
                            this.iSconn = this._plc.IsConnected;
                        }
                        else
                        {
                            this.iSconn = this._plc.IsConnected;
                        }
                    }));
                }
            }
        }
        /// <summary>
        /// 向PLC写入Int类型
        /// </summary>
        /// <param name="DBaddress">DB地址</param>
        /// <param name="value">值</param>
        /// <returns></returns>
        public bool WritePlcInt32(string DBaddress, string value)
        {
            if (this._plc != null)
            {
                if (!this.iSconn)
                {
                    //PLC未连接，正在尝试重连！
                    this._plc.Open();
                    WritePlcInt32(DBaddress, value);
                    return true;
                }

                this._plc.Write(DBaddress, value);
                return true;
            }
            else
            {
                //PLC未初始化!
                return false;
            }
        }
        /// <summary>
        /// 向PLC写入Int16位
        /// </summary>
        /// <param name="DBaddress"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public bool WritePlcInt16(string DBaddress, string value)
        {
            if (this._plc != null)
            {
                if (!this.iSconn)
                {
                    //PLC未连接，正在尝试重连！
                    this._plc.Open();
                    WritePlcInt16(DBaddress, value);
                    return true;
                }

                this._plc.Write(DBaddress, value);
                return true;
            }
            else
            {
                //PLC未初始化!
                return false;
            }
        }
        /// <summary>
        /// 写入Byte
        /// </summary>
        /// <param name="DBaddress"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public bool WritePlcByte(string DBaddress, string value)
        {

            if (this._plc != null)
            {
                Tuple<int, int> tuple = GetString(DBaddress);
                if (!this.iSconn)
                {
                    //PLC未连接，正在尝试重连！
                    this._plc.Open();
                    WritePlcByte(DBaddress, value);
                    return true;
                }

                this._plc.WriteBytes(DataType.Memory, tuple.Item1, tuple.Item2, Encoding.UTF8.GetBytes(value));
                return true;
            }
            else
            {
                //PLC未初始化!
                return false;
            }

        }
        /// <summary>
        /// 读取PLC内部数据
        /// </summary>
        /// <typeparam name="T">T作为类型推断根据传入的类型返回数据</typeparam>
        /// <param name="value">类型</param>
        /// <param name="address">地址</param>
        /// <returns></returns>
        public T ReadPlc<T>(T type, string address)
        {
            if (this._plc != null)
            {

                if (!this.iSconn)
                {
                    //PLC未连接，正在尝试重连！
                    this._plc.Open();
                    T t = ReadPlc(type, address);
                    return t;
                }

                T d = (T)this._plc.Read(address);
                return d;
            }
            else
            {
                //PLC未初始化!
                return default(T);
            }
        }

        /// <summary>
        /// 字符串处理
        /// </summary>
        /// <param name="strvalue"></param>
        /// <returns></returns>
        private Tuple<int, int> GetString(string strvalue)
        {
            //首先提取我需要的字符串
            var str = _address.Split('.');
            //再次拆解
            var db = Convert.ToInt32(str[0].Where(s => int.TryParse($"{s}", out int _)));
            var startByte = Convert.ToInt32(str[1].Where(s => int.TryParse($"{s}", out int _)));
            return Tuple.Create(db, startByte);
        }


        public void GetAllPlcDataAddress(Dictionary<Type,List<string>> DataAddresss)
        {
       
            foreach (var dataAddress in DataAddresss)
            {
                switch (dataAddress.Key)
                {
                    case Type.Bool:
                        foreach (var item in dataAddress.Value)
                        {
                            addrssList.Add(item, string.Empty);
                        }
                        break;
                    case Type.Int16:
                        foreach (var item in dataAddress.Value)
                        {
                            addrssList.Add(item, string.Empty);
                        }
                        break;
                    case Type.Int32:
                        foreach (var item in dataAddress.Value)
                        {
                            addrssList.Add(item, string.Empty);
                        }
                        break;
                    case Type.String:
                        foreach (var item in dataAddress.Value)
                        {
                            addrssList.Add(item, string.Empty);
                        }
                        break;
                    case Type.Real:
                        foreach (var item in dataAddress.Value)
                        {
                            addrssList.Add(item, string.Empty);
                        }
                        break;
                    default:
                        ErrorViewModel.Errornotice("类型错误！不支持的类型！", true);
                        break;
                }

            }
             System.Threading.Tasks.Task task = new System.Threading.Tasks.Task(() =>
             {
                //Application.Current.Dispatcher.BeginInvoke(new Action(() => {
                //}));
                int j = 0;
                while (true)
                {
                    addrssList[DataAddresss[Type.Bool][j]] = ReadPlc(true, addrssList[DataAddresss[Type.Bool][j]]).ToString();
                    addrssList[DataAddresss[Type.Int16][j]] = ReadPlc(1, addrssList[DataAddresss[Type.Bool][j]]).ToString();
                    addrssList[DataAddresss[Type.Int32][j]] = ReadPlc(10, addrssList[DataAddresss[Type.Bool][j]]).ToString();
                    addrssList[DataAddresss[Type.String][j]] = ReadPlc("", addrssList[DataAddresss[Type.Bool][j]]).ToString();
                    addrssList[DataAddresss[Type.Real][j]] = ReadPlc(1.1, addrssList[DataAddresss[Type.Bool][j]]).ToString();
                    j++; if (j == addrssList.Count) j = 0;
                }
             });
          
        }
    }
}
